package com.gitee.aurora.utils;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gitee.aurora.comm.Constant;
import com.gitee.aurora.server.service.SjjcLogInfoService;
import com.gitee.aurora.server.vo.SjjcLogInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.web.client.RestTemplate;

@ServerEndpoint(value = "/webSocket/{deviceId}")
@Component
public class WebSocketServer {

    private static final Logger logger = LoggerFactory.getLogger(WebSocketServer.class);
    public ObjectMapper mapper = new ObjectMapper();

    /**
     * 存放每个客户端对应的MyWebSocket对象
     */
    private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
    private SjjcLogInfoService sjjcLogInfoService = SpringUtils.getBean(SjjcLogInfoService.class);


    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private Session session;
    /* @Autowired
     private PtConfigService ptConfigService;
 */
    @Resource
    private RestTemplate restTemplate;

    //  @Autowired
    // private AuroraJdbcTemplate auroraJdbcTemplate;
    /**
     * 连接建立成功调用的方法
     * */
    @OnOpen
    public void onOpen(Session session,@PathParam(value = "deviceId") String deviceId) {
        System.out.println("服务端接收信息-------------------------");
        this.session = session;
        //判断当前设备是否已有web socket连接，有则删除
        deleteWebsocketExisted(deviceId);
        //保存当前websocket连接
        webSocketMap.put(deviceId, this);

        // 通知客户端建立连接成功
        sendMessage(deviceId + "connected success");

        //设备状态变化(设备连接成功通知)
        statusChange(deviceId, true);
    }

    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     * */
    @OnMessage
    public void onMessage(String message) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        Map sjjcLo= mapper.readValue(message, Map.class);
        SjjcLogInfo sjjcLogInfo=new SjjcLogInfo();
        sjjcLogInfo.setCode(sjjcLo.get(Constant.code).toString());
        sjjcLogInfo.setMessage(mapper.writeValueAsString(sjjcLo.get(Constant.message)));
        sjjcLogInfo.setStatus(Constant.zstatus);
        sjjcLogInfoService.insertSjjcLogInfo(sjjcLogInfo);
        if("ping".equals(message)){
            // 心跳
            sendMessage(message);
        }else{
            // 省略业务消息处理步骤
            // 返回消息给客户端
            sendMessage("some message");
        }
    }

    /**
     * 连接关闭调用的方法
     * */
    @OnClose
    public void onClose() {
        String deviceId =  getKey(webSocketMap, this);
        // 从set中删除
        webSocketMap.remove(deviceId);
        //设备下线
        statusChange(deviceId, false);
    }

    /**
     * 发生错误时调用
     * */
    @OnError
    public void onError(Throwable error) {
        logger.error("Error:"+error.getMessage());
    }

    private void statusChange(String deviceId, boolean status) {
        if (status) {
            logger.info("组件编号:{}上线", deviceId);
        }else{
            logger.info("组件编号:{}下线", deviceId);
        }
        // 省略操作数据库步骤
    }


    private void deleteWebsocketExisted(String deviceId) {
        WebSocketServer oldConnection = webSocketMap.get(deviceId);
        if(null != oldConnection){
            try {
                oldConnection.getSession().close();
            } catch (IOException e) {
                logger.error("IOException:{}"+e.getMessage());
            }
        }
    }

    /**
     * 根据map的value获取map的key
     * @param map
     * @param myWebSocket
     * @return
     */
    private static String getKey(Map<String,WebSocketServer> map, WebSocketServer myWebSocket){
        String key="";
        for (Map.Entry<String, WebSocketServer> entry : map.entrySet()) {
            if(myWebSocket.equals(entry.getValue())){
                key=entry.getKey();
            }
        }
        return key;
    }

    public void sendMessage(String message) {
        this.session.getAsyncRemote().sendText(message);
    }

    public Session getSession() {
        return session;
    }

}
